home *** CD-ROM | disk | FTP | other *** search
/ Windows Expert / Windows Expert.iso / windownt / uupc11ys.zip / LIB / SSLEEP.C < prev    next >
C/C++ Source or Header  |  1993-04-10  |  16KB  |  453 lines

  1. /*--------------------------------------------------------------------*/
  2. /*    s s l e e p . c                                                 */
  3. /*                                                                    */
  4. /*    Smart sleep routines for UUPC/extended                          */
  5. /*                                                                    */
  6. /*    Written by Dave Watt, modified by Drew Derbyshire               */
  7. /*                                                                    */
  8. /*    Generates DOS specific code with Windows support by default,    */
  9. /*    generates call to OS/2 family API if FAMILYAPI is defined       */
  10. /*    generates calls to Windows/NT if WIN32 is defined               */
  11. /*--------------------------------------------------------------------*/
  12.  
  13. /*--------------------------------------------------------------------*/
  14. /*                          RCS Information                           */
  15. /*--------------------------------------------------------------------*/
  16.  
  17. /*
  18.  *    $Id: SSLEEP.C 1.4 1993/04/11 00:32:29 ahd Exp $
  19.  *
  20.  *    Revision history:
  21.  *    $Log: SSLEEP.C $
  22.  *     Revision 1.4  1993/04/11  00:32:29  ahd
  23.  *     Global edits for year, TEXT, etc.
  24.  *
  25.  * Revision 1.3  1992/12/12  16:12:13  ahd
  26.  * Correct test for DesqView
  27.  *
  28.  * Revision 1.2  1992/12/07  02:43:20  ahd
  29.  * Add DesqView support from David M. Watt
  30.  *
  31.  * Revision 1.1  1992/11/16  05:00:26  ahd
  32.  * Initial revision
  33.  *
  34.  */
  35.  
  36. /*--------------------------------------------------------------------*/
  37. /*                        System include files                        */
  38. /*--------------------------------------------------------------------*/
  39.  
  40. #include <limits.h>
  41. #include <stdio.h>
  42. #include <stdlib.h>
  43. #include <signal.h>
  44. #include <time.h>
  45.  
  46. /*--------------------------------------------------------------------*/
  47. /*               MS-DOS and OS/2 specific include files               */
  48. /*--------------------------------------------------------------------*/
  49.  
  50. #ifdef FAMILYAPI
  51.  
  52. #define INCL_NOPM
  53. #define INCL_BASE
  54. #include <os2.h>
  55.  
  56. #else
  57.  
  58. #include <dos.h>
  59. #include <sys/timeb.h>
  60.  
  61. #endif
  62.  
  63. #ifdef WIN32
  64. #include <windows.h>
  65. #endif
  66.  
  67. /*--------------------------------------------------------------------*/
  68. /*                    UUPC/extended include files                     */
  69. /*--------------------------------------------------------------------*/
  70.  
  71. #include "lib.h"
  72. #include "ssleep.h"
  73. #include "safeio.h"
  74.  
  75. /*--------------------------------------------------------------------*/
  76. /*                          Global variables                          */
  77. /*--------------------------------------------------------------------*/
  78.  
  79. currentfile();
  80.  
  81. /*--------------------------------------------------------------------*/
  82. /*                     MS-DOS specific functions                      */
  83. /*--------------------------------------------------------------------*/
  84.  
  85. #ifndef FAMILYAPI
  86. #define MULTIPLEX 0x2F
  87. #define DESQVIEW 0x15
  88.  
  89. #ifdef _Windows
  90.  
  91. #include <windows.h>
  92.  
  93. void WindowsDelay( int milliseconds );
  94.  
  95. /*--------------------------------------------------------------------*/
  96. /*    W i n d o w s D e l a y                                         */
  97. /*                                                                    */
  98. /*    Delay processing under Windows                                  */
  99. /*--------------------------------------------------------------------*/
  100.  
  101. void WindowsDelay( int milliseconds )
  102. {
  103.    WORD TimerId = SetTimer( NULL, 0,
  104.             milliseconds ? (WORD) milliseconds : (WORD) 1,
  105.             NULL );
  106.  
  107.    if ( TimerId == 0 )
  108.    {
  109.       printmsg(0, "WindowsDelay: Unable to set Windows Timer");
  110.       return;
  111.    } /* if */
  112.  
  113.    WaitMessage();
  114.  
  115.    if ( !KillTimer( NULL, TimerId ) )
  116.       printmsg(0, "WindowsDelay: Unable to kill Windows Timer %d",
  117.                   (int) TimerId );
  118.  
  119. } /* WindowsDelay */
  120.  
  121. #else
  122.  
  123. #ifndef WIN32
  124.  
  125. /*--------------------------------------------------------------------*/
  126. /*                      Local function declares                       */
  127. /*--------------------------------------------------------------------*/
  128.  
  129. static void WinGiveUpTimeSlice(void);
  130. static int RunningUnderWindows(void);
  131. static int RunningUnderDesqview(void);
  132. static void DVGiveUpTimeSlice(void);
  133.  
  134. /*--------------------------------------------------------------------*/
  135. /*              Use this first to see if the rest are OK              */
  136. /*                                                                    */
  137. /*                  MOV AX,1600h   ; Check for win386/win3.0          */
  138. /*                                   present                          */
  139. /*                  INT 2Fh                                           */
  140. /* Return AL = 0 -> No Windows, AL = 80 -> No WIn386 mode             */
  141. /*        AL = 1 or AL = FFh -> Win386 2.xx running                   */
  142. /*   else AL = Major version (3), AH = Minor version                  */
  143. /*--------------------------------------------------------------------*/
  144. /* --------------- Release time slice                                 */
  145. /*                  MOV AX,1680h   ; **** Release time slice          */
  146. /*                  INT 2Fh        ; Let someone else run             */
  147. /* Return code is AL = 80H -> service not installed, AL = 0 -> all    */
  148. /*                                                              OK    */
  149. /*--------------------------------------------------------------------*/
  150. /* --------------- Enter critical section (disable task switch)       */
  151. /*                  MOV AX,1681H   ; Don't tread on me!               */
  152. /*                  INT 2Fh                                           */
  153. /*--------------------------------------------------------------------*/
  154. /* --------------- End critical section (Permit task switching)       */
  155. /*                  MOV AX,1682h                                      */
  156. /*                  INT 2Fh                                           */
  157. /*--------------------------------------------------------------------*/
  158.  
  159. /*--------------------------------------------------------------------*/
  160. /*    R u n n i n g U n d e r W i n d o w s                           */
  161. /*                                                                    */
  162. /*    Determines if we are running under MS-Windows 386 or            */
  163. /*    MS-Windows 3.  We save the result, to avoid excessively         */
  164. /*    disabling interrupts when in a spin loop.                       */
  165. /*--------------------------------------------------------------------*/
  166.  
  167. static int RunningUnderWindows(void)
  168. {
  169.  
  170.    static int result = 2;
  171.    union REGS inregs, outregs;
  172.    int irq;
  173.  
  174.    if (result != 2)           /* First call?                         */
  175.       return result;          /* No --> Return saved result          */
  176.  
  177.    irq = MULTIPLEX;
  178.    inregs.x.ax = 0x1600;
  179.    int86(irq, &inregs, &outregs);
  180.    if ( (outregs.h.al & 0x7f) == 0)
  181.       result = 0;
  182.    else
  183.       result = 1;
  184.  
  185.    return result;
  186.  
  187. } /* RunningUnderWindows */
  188.  
  189. /*--------------------------------------------------------------------*/
  190. /*    W i n G i v e U p T i m e S l i c e                             */
  191. /*                                                                    */
  192. /*    Surrender our time slice when executing under Windows/386       */
  193. /*    or Windows release 3.                                           */
  194. /*--------------------------------------------------------------------*/
  195.  
  196. static void WinGiveUpTimeSlice(void)
  197. {
  198.    union REGS inregs, outregs;
  199.    int irq = MULTIPLEX;
  200.  
  201.    inregs.x.ax = 0x1680;
  202.    int86(irq, &inregs, &outregs);
  203.    if (outregs.h.al != 0) {
  204.       printmsg(0,"Problem giving up timeslice:  %u\n", outregs.h.al);
  205.       panic();
  206.    }
  207. } /* WinGiveUpTimeSlice */
  208.  
  209. /*--------------------------------------------------------------------*/
  210. /*    R u n n i n g U n d e r D e s q v i e w                         */
  211. /*                                                                    */
  212. /*    Returns TRUE if running under that OTHER DOS multi-tasker.      */
  213. /*--------------------------------------------------------------------*/
  214.  
  215. static int RunningUnderDesqview(void)
  216. {
  217.    static int result = 2;
  218.    union REGS inregs, outregs;
  219.  
  220.    if (result != 2)           /* First call?                         */
  221.       return result;          /* No --> Return saved result          */
  222.  
  223.    inregs.x.ax = 0x2B01;      /* Dos Set Date function */
  224.    inregs.x.cx = 0x4445;      /* CX DX = 'DESQ' */
  225.    inregs.x.dx = 0x5351;
  226.  
  227.    intdos(&inregs, &outregs);
  228.    if (outregs.h.al == 0xff) {
  229.       result = 0;
  230.    } else {
  231.       printmsg(4, "RunningUnderDesqview:  Running under DesqView (AX=0x%x)",
  232.                (int) outregs.x.ax);
  233.       result = 1;
  234.    }
  235.  
  236.    return result;
  237.  
  238. } /* RunningUnderDesqview */
  239.  
  240. /*--------------------------------------------------------------------*/
  241. /*    D V G i v e U p T i m e S l i c e                               */
  242. /*                                                                    */
  243. /*    Surrender the CPU under DesqView                                */
  244. /*--------------------------------------------------------------------*/
  245.  
  246. static void DVGiveUpTimeSlice(void)
  247. {
  248. #ifdef __TURBOC__
  249.    asm {
  250. #else
  251.    _asm \
  252.       {
  253. #endif
  254.       push ax
  255.       mov ax, 101AH
  256.                               /* Switch over to Desqview's stack  */
  257.       int     15H
  258.       mov ax, 1000H
  259.                               /* Give up the timeslice            */
  260.       int     15H
  261.       mov ax, 1025H
  262.                               /* Switch stack back to application */
  263.       int     15H
  264.       pop ax
  265.       }
  266.  
  267. } /* DVGiveUpTimeSlice */
  268.  
  269. #endif /* _Windows */
  270. #endif /* WIN32 */
  271. #endif
  272.  
  273.  
  274. /*--------------------------------------------------------------------*/
  275. /*    ssleep() - wait n seconds                                       */
  276. /*                                                                    */
  277. /*    Simply delay until n seconds have passed.                       */
  278. /*--------------------------------------------------------------------*/
  279.  
  280. void ssleep(time_t interval)
  281. {
  282.    time_t start = time((time_t *)NULL);
  283.    time_t left = interval;
  284.  
  285. /*--------------------------------------------------------------------*/
  286. /*            Break the spin into chunks ddelay can handle            */
  287. /*--------------------------------------------------------------------*/
  288.  
  289.    while ( (left*1000L) > (long) INT_MAX )
  290.    {
  291.       ddelay( 5000 );         /* Five seconds per pass               */
  292.       left = max(interval - (time( NULL ) - start),0);
  293.    } /* while */
  294.  
  295. /*--------------------------------------------------------------------*/
  296. /*                 Final delay for the time remaining                 */
  297. /*--------------------------------------------------------------------*/
  298.  
  299.    ddelay( (int) (left * 1000L) );
  300.  
  301. } /*ssleep*/
  302.  
  303. /*--------------------------------------------------------------------*/
  304. /*    d d e l a y                                                     */
  305. /*                                                                    */
  306. /*    Delay for an interval of milliseconds                           */
  307. /*--------------------------------------------------------------------*/
  308.  
  309. void   ddelay   (int milliseconds)
  310. {
  311.  
  312. #ifdef FAMILYAPI
  313.    USHORT result;
  314. #else
  315.    struct timeb t;
  316.    time_t seconds;
  317.    unsigned last;
  318. #endif
  319.  
  320. #ifndef _Windows
  321.  
  322. /*--------------------------------------------------------------------*/
  323. /*           Check for user aborts via the ESC (escape) key           */
  324. /*--------------------------------------------------------------------*/
  325.  
  326.    if (bflag[F_ESCAPE])       /* Special Ctrl-C processing avail?    */
  327.    {
  328.       boolean beep = TRUE;
  329.  
  330.       while (safepeek())      /* Yes --> While character in buffer   */
  331.       {
  332.          if (safein() == '\033') /* Look for ESC                     */
  333.             raise( SIGINT );     /* Yes --> eject via std exit       */
  334.          else if ( beep )
  335.          {
  336.              putchar('\a');      /* No --> Complain to user          */
  337.              beep = FALSE;       /* But be nice about it ...
  338.                                     only once per pass through here  */
  339.          } /* else if ( beep ) */
  340.       } /* while */
  341.  
  342.    } /* if (bflag[F_ESCAPE]) */
  343.  
  344. #endif /* _Windows */
  345.  
  346. /*--------------------------------------------------------------------*/
  347. /*                          Now do the wait                           */
  348. /*--------------------------------------------------------------------*/
  349.  
  350. /*--------------------------------------------------------------------*/
  351. /*                          Windows/NT wait                           */
  352. /*--------------------------------------------------------------------*/
  353.  
  354. #ifdef WIN32
  355.    Sleep(milliseconds);
  356.  
  357. /*--------------------------------------------------------------------*/
  358. /*                             OS/2 wait                              */
  359. /*--------------------------------------------------------------------*/
  360.  
  361. #elif FAMILYAPI
  362.    result = DosSleep(milliseconds);
  363.    if (result != 0)
  364.       panic();
  365. #else
  366.  
  367. /*--------------------------------------------------------------------*/
  368. /*                            MS-DOS wait                             */
  369. /*--------------------------------------------------------------------*/
  370.  
  371. #ifndef _Windows
  372.  
  373. #ifdef __TURBOC__
  374.    enable();
  375. #else
  376.    _enable();
  377. #endif
  378.  
  379. #endif
  380.  
  381. /*--------------------------------------------------------------------*/
  382. /*       Handle the special case of 0 delay, which is simply a        */
  383. /*                  request to give up our timeslice                  */
  384. /*--------------------------------------------------------------------*/
  385.  
  386.    if (milliseconds == 0)     /* Make it compatible with DosSleep    */
  387.    {
  388.  
  389. #ifdef _Windows
  390.       WindowsDelay( milliseconds );
  391. #else
  392.  
  393.       if (RunningUnderWindows())
  394.          WinGiveUpTimeSlice( );
  395.       else if (RunningUnderDesqview())
  396.          DVGiveUpTimeSlice();
  397.  
  398. #endif
  399.       return;
  400.    } /* if */
  401.  
  402.    ftime(&t);                 /* Get a starting time                 */
  403.    last = t.millitm;          /* Save milliseconds portion           */
  404.    seconds = t.time;          /* Save seconds as well                */
  405.  
  406.    while( milliseconds > 0)   /* Begin the spin loop                 */
  407.    {
  408.  
  409. #ifdef _Windows
  410.  
  411.       WindowsDelay( milliseconds );
  412.  
  413. #else
  414.       if (RunningUnderWindows())
  415.          WinGiveUpTimeSlice();
  416.       else if (RunningUnderDesqview())
  417.          DVGiveUpTimeSlice();
  418.       else {
  419.  
  420. #ifdef __TURBOC__
  421.  
  422.          delay( milliseconds );
  423.  
  424. #else
  425.  
  426.          int volatile count;  /* Don't let compiler optimize this    */
  427.          for ( count = 0; count < 2400; count ++);
  428.                               /* We spin so that interrupts are
  429.                                  enabled for most of the loop        */
  430. #endif
  431.  
  432.       } /* else */
  433. #endif /* _Windows */
  434.  
  435.       ftime(&t);              /* Take a new time check               */
  436.  
  437.       if (t.time == seconds)  /* Same second as last pass?           */
  438.          milliseconds -= (t.millitm - last); /* Yes --> mSecond delta*/
  439.       else
  440.          milliseconds -= 1000 * (int) (t.time - seconds)
  441.                               - (last - t.millitm);
  442.                               /* No --> Handle wrap of mSeconds      */
  443.  
  444.       last = t.millitm;       /* Update last tick indicator          */
  445.       seconds = t.time;       /* Update this as well; only needed if
  446.                                  it changed (see above), but it
  447.                                  kills time (which is our job)       */
  448.    } /* while */
  449.  
  450. #endif /* FAMILYAPI */
  451.  
  452. } /* ddelay */
  453.